1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 *
19 */
20 package org.apache.mina.util;
21
22 import java.io.IOException;
23 import java.io.LineNumberReader;
24 import java.io.PrintWriter;
25 import java.io.StringReader;
26 import java.io.StringWriter;
27 import java.util.ArrayList;
28
29 /**
30 * Utility class for working with xml data
31 *
32 * Implementation is heavily based on org.apache.log4j.helpers.Transform
33 *
34 * @author <a href="http://mina.apache.org">Apache MINA Project</a>
35 */
36 public class Transform {
37
38 private static final String CDATA_START = "<![CDATA[";
39 private static final String CDATA_END = "]]>";
40 private static final String CDATA_PSEUDO_END = "]]>";
41 private static final String CDATA_EMBEDED_END = CDATA_END + CDATA_PSEUDO_END + CDATA_START;
42 private static final int CDATA_END_LEN = CDATA_END.length();
43
44 /**
45 * This method takes a string which may contain HTML tags (ie,
46 * <b>, <table>, etc) and replaces any
47 * '<', '>' , '&' or '"'
48 * characters with respective predefined entity references.
49 *
50 * @param input The text to be converted.
51 * @return The input string with the special characters replaced.
52 * */
53 static public String escapeTags(final String input) {
54 // Check if the string is null, zero length or devoid of special characters
55 // if so, return what was sent in.
56
57 if(input == null
58 || input.length() == 0
59 || (input.indexOf('"') == -1 &&
60 input.indexOf('&') == -1 &&
61 input.indexOf('<') == -1 &&
62 input.indexOf('>') == -1)) {
63 return input;
64 }
65
66 StringBuilder buf = new StringBuilder(input.length() + 6);
67 char ch;
68
69 int len = input.length();
70 for(int i=0; i < len; i++) {
71 ch = input.charAt(i);
72 if (ch > '>') {
73 buf.append(ch);
74 } else if(ch == '<') {
75 buf.append("<");
76 } else if(ch == '>') {
77 buf.append(">");
78 } else if(ch == '&') {
79 buf.append("&");
80 } else if(ch == '"') {
81 buf.append(""");
82 } else {
83 buf.append(ch);
84 }
85 }
86 return buf.toString();
87 }
88
89 /**
90 * Ensures that embeded CDEnd strings (]]>) are handled properly
91 * within message, NDC and throwable tag text.
92 *
93 * @param buf StringBuffer holding the XML data to this point. The
94 * initial CDStart (<![CDATA[) and final CDEnd (]]>) of the CDATA
95 * section are the responsibility of the calling method.
96 * @param str The String that is inserted into an existing CDATA Section within buf.
97 * */
98 static public void appendEscapingCDATA(final StringBuffer buf,
99 final String str) {
100 if (str != null) {
101 int end = str.indexOf(CDATA_END);
102 if (end < 0) {
103 buf.append(str);
104 } else {
105 int start = 0;
106 while (end > -1) {
107 buf.append(str.substring(start, end));
108 buf.append(CDATA_EMBEDED_END);
109 start = end + CDATA_END_LEN;
110 if (start < str.length()) {
111 end = str.indexOf(CDATA_END, start);
112 } else {
113 return;
114 }
115 }
116 buf.append(str.substring(start));
117 }
118 }
119 }
120
121 /**
122 * convert a Throwable into an array of Strings
123 * @param throwable
124 * @return string representation of the throwable
125 */
126 public static String[] getThrowableStrRep(Throwable throwable) {
127 StringWriter sw = new StringWriter();
128 PrintWriter pw = new PrintWriter(sw);
129 throwable.printStackTrace(pw);
130 pw.flush();
131 LineNumberReader reader = new LineNumberReader(new StringReader(sw.toString()));
132 ArrayList<String> lines = new ArrayList<String>();
133 try {
134 String line = reader.readLine();
135 while(line != null) {
136 lines.add(line);
137 line = reader.readLine();
138 }
139 } catch(IOException ex) {
140 lines.add(ex.toString());
141 }
142 String[] rep = new String[lines.size()];
143 lines.toArray(rep);
144 return rep;
145 }
146
147 }